package com.cocotingo.snail.template.models;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.cocotingo.snail.template.TemplateSyntaxException;
import com.cocotingo.snail.template.XMLTemplateWritter;

public class ViewNode extends AttributedNode {
	
	private String className, templateName;
	private final List<ViewNode> subviews;
	private HandlerNode handler;
	private LayoutNode layout;
	private PaintNode paint;
	private PreviewNode preview;
	
	public ViewNode() {
		subviews = new ArrayList<ViewNode>(0);
	}
	
	public String getClassName() {
		return className;
	}
	
	public String getTemplateName() {
		return templateName;
	}
	
	public void setClassName(String className) {
		this.className = className;
	}
	
	public void setTemplateName(String templateName) {
		this.templateName = templateName;
	}
	
	public LayoutNode getLayoutNode() {
		return layout;
	}
	
	public void setLayoutNode(LayoutNode layout) {
		this.layout = layout;
	}
	
	public PaintNode getPaintNode() {
		return paint;
	}
	
	public void setPaintNode(PaintNode paint) {
		this.paint = paint;
	}
	
	public PaintNode getPreviewNode() {
		return preview;
	}
	
	public void setPreviewNode(PreviewNode preview) {
		this.preview = preview;
	}
	
	public final void addViewNode(ViewNode node) {
		this.addViewNode(node, subviews.size());
	}
	
	public void addViewNode(ViewNode node, int index) {
		if (node == null) throw new IllegalArgumentException("cannot add null as a child node");
		subviews.add(index, node);
	}
	
	public boolean removeViewNode(ViewNode node) {
		return subviews.remove(node);
	}
	
	public Iterable<ViewNode> viewNodes() {
		return new Iterable<ViewNode>() {
			@Override
			public Iterator<ViewNode> iterator() {
				return subviews.iterator();
			}
		};
	}
	
	public int viewNodeCount() {
		return subviews.size();
	}
	
	public HandlerNode getHandlerNode() {
		return handler;
	}
	
	public void setHandlerNode(HandlerNode handler) {
		this.handler = handler;
	}
	
	@Override
	public void validateNode() throws TemplateSyntaxException {
		if (getID() != null) super.validateNode();
		if (!isEmptyOrNull(className) && !isEmptyOrNull(templateName))
			throw new TemplateSyntaxException(this, "Cannot specify both ViewNode.className and ViewNode.templateName.");
	}
	
	private static boolean isEmptyOrNull(String str) {
		return str == null || str.isEmpty();
	}
	
	@Override
	public Iterable<Node> children() {
		return new Iterable<Node>() {
			int it = 0;
			Iterator<ViewNode> it0 = subviews.iterator();
			@Override
			public Iterator<Node> iterator() {
				return new Iterator<Node>() {

					@Override
					public boolean hasNext() {
						if (it == 0) {
							if (it0.hasNext()) return true;
							else it = 1;
						}
						if (it == 1) {
							if (handler != null) return true;
							else it = 2;
						}
						if (it == 2) {
							if (layout != null) return true;
							else it = 3;
						}
						if (it == 3) {
							if (paint != null) return true;
							else it = 4;
						}
						if (it == 4) {
							if (preview != null) return true;
							else it = 5;
						}
						return false;
					}

					@Override
					public Node next() {
						if (it == 0) {
							return it0.next();
						}
						if (it == 1) {
							it++;
							return handler;
						}
						if (it == 2) {
							it++;
							return layout;
						}
						if (it == 3) {
							it++;
							return paint;
						}
						if (it == 4) {
							it++;
							return preview;
						}
						return null;
					}

					@Override
					public void remove() {
						throw new UnsupportedOperationException();
					}
					
				};
			}
		};
	}

	@Override
	protected String getXMLNodeName() {
		return "View";
	}

	@Override
	protected String getXMLAttributes() {
		StringBuffer buf = new StringBuffer();
		if (getID() != null && !getID().isEmpty()) {
			buf.append(String.format(" id=\"%s\"", getID()));
		}
		if (className != null) {
			buf.append(String.format(" class=\"%s\"", className));
		}
		if (templateName != null) {
			buf.append(String.format(" template=\"%s\"", templateName));
		}
		for (Attribute attribute : attributes()) {
			buf.append(String.format(" %s=\"%s\"", attribute.getName(), XMLTemplateWritter.escapeXMLCharacters(attribute.getValue())));
		}
		if (buf.length() > 0 && buf.charAt(0) == ' ') {
			return buf.substring(1);
		} else {
			return buf.toString();
		}
	}
	
}
